/**
 * 描述：使用数组来进行循环队列的模拟
 *
 * @author WangB
 * @create 2018-10-20-0:26
 */
public class LoopQueue<E> implements Queue<E> {
    private E[] data;
    private int front;//队首的索引
    private int tail;//队尾的下一个元素的位置。
    private int size;//队列中的元素

    public LoopQueue(int capacity){
        /**
         * 用户希望传进来capacity。因为我们的队列中有一个元素是不用的，因此需要将大小加1
         */
        data = (E[])(new Object[capacity + 1]);
        front = 0 ;
        tail = 0 ;
        size = 0;

    }

    public LoopQueue(){
       this(10);//调用有参数的这个构造函数
    }

    public int getCapacity(){
        return data.length - 1 ;
    }

     @Override
    public boolean isEmpty(){
        return tail == front;
     }
    @Override
    public int getSize(){
        return size;
    }

    @Override

    public void enqueue(E e){
        if((tail+1)%data.length ==front)
            resize(getCapacity()*2);

        data[tail] = e ;
        tail = (tail + 1)%data.length;
        size++;

    }
    @Override
    public E dequeue(){
        if(isEmpty())
            throw new IllegalArgumentException("队列为空了");
        E ret = data[front];
        data[front] = null;
        front=(front+1)%data.length;
        size--;
        if(size == getCapacity()/4 && getCapacity() / 2!= 0)
            resize(getCapacity()/2);
        return ret;
    }
    @Override

    public E getFront()
    {
        if(isEmpty())
            throw new IllegalArgumentException("队列空了");
        return data[front];
    }
    private void resize(int newCapacity)
    {
        E[] newData = (E[])(new Object[newCapacity + 1]);
        for (int i = 0; i < size; i++) {
            newData[i] = data[(i + front)%data.length];
        }
        data = newData;
        front = 0 ;
        tail = size;
    }

    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append(String.format("LoopQueue:size=%d,capacity=%d\n",size,getCapacity()));
        res.append("front[");
        for (int i = front; i != tail ; i=(i + 1)%data.length) {
            res.append(data[i]);
            if((i + 1)%data.length != tail)
                res.append(',');
        }
        res.append("]tail");
        return res.toString();
    }


    public static void main(String[] args)
    {
        //循环队列测试样例
        LoopQueue<Integer> queue = new LoopQueue <> ();
        for (int i = 0; i < 13; i++) {
            queue.enqueue(i);
            System.out.println(queue);
            if(i % 3 == 2){
                queue.dequeue();
                System.out.println(queue);
            }

        }


    }
}